# 1. Used to created database table
from flask_sqlalchemy import SQLAlchemy

# 2. `extensions` Model used for ensecrit password
from blog.extensions import bcrypt

#: Used to operate database and table and data
db = SQLAlchemy()

#: Many to Many
#: `posts` and `tags` table relationship
posts_tags = db.Table(
	'posts_tags',
	db.Column('post_id', db.String(45), db.ForeignKey('posts.id')),
	db.Column('tag_id', db.String(45), db.ForeignKey('tags.id')))

#: Many to Many
#: `roles` and `users` table relationship
users_roles = db.Table('users_roles',
	db.Column('user_id', db.String(45), db.ForeignKey('users.id')),
	db.Column('role_id', db.String(45), db.ForeignKey('roles.id')))


class User(db.Model):
	""" Represent Protected `users` """

	# Set the table name for `users`
	__tablename__ = 'users'
	
	id = db.Column(db.String(45), primary_key=True)
	username = db.Column(db.String(200))
	password = db.Column(db.String(200))

	# Establish contact with Post's ForeignKey: user_id
	# Pass the Post talbe to contact with User in the `users` of instance_Post
	# How to use:
	# 1 User <=> Post by `user.id` of User:ins_post.user_id = ins_user.id
	# 2 Post <=> User by `users` of backref:ins_post.users = ins_user
	
	posts = db.relationship(
		'Post',
		backref = 'users',
		lazy = 'dynamic')
	
	''' delete the post_record when delete a user. '''
	#:posts = db.relationship(
	#:	'Post',
	#:	backref = 'users',
	#:	lazy = 'dynamic',
	#:	cascade='all, delete, delete-orphan')
	
	
	# Roles userd to distribute previlige 
	roles = db.relationship(
		'Role',
		secondary=users_roles,
		backref=db.backref('users', lazy='dynamic'))
	
	"""
	flask.ext.login the class of User must come true under method:
	
	`is_authenticated`
	`is_active`
	`is_anonymous`
	`get_id`
	
	"""
	
	# Whether authenticated
	def is_authenticated(self):
		""" Check whether logged in and `AnoymouseUserMixin` """
		if isinstance(self, AnonymousUserMixin):
			return False
		else:
			return True
	
	# Whether active
	def is_active(self):
		return True
	
	# Whether anonymous
	def is_anonymous(self):
		""" Check users's login status """
		
		if isinstance(self, AnonymousUserMixin):
			return True
		else:
			return False
	
	# Get id
	def get_id(self):
		return self.id
	
	#: Bcrypt.Set user password
	def set_password(self, password):
		return bcrypt.generate_password_hash(password).decode('utf-8')	
	
	#: Bcrypt.Check password
	def check_password(self, password):
		return bcrypt.check_password_hash(self.password, password)	
	
	# def check_password(self, hash_key, password):
	#	return bcrypt.check_password_hash(hash_key, password)	
		
	# INIT the User's property of `id` `username` `password`
	def __init__(self, id, username, password):
		self.id = id
		self.username = username
		
		# encrypt password pass by calling `set_password()`
		self.password = self.set_password(password)
	
	# RETURN `<Model User {username}>` when print the User instance
	def __repr__(self):
		return "<Model User `{}`>".format(self.username)


class Role(db.Model):
	""" Init the Model `roles` """
	
	__tablename__ = 'roles'
	
	id = db.Column(db.String(45), primary_key=True)
	name = db.Column(db.String(255), unique=True)
	description = db.Column(db.String(255))
	
	def __init__(self, id, name):
		self.id = id 
		self.name = name
	
	def __repr__(self):
		return "<Model Role `{}`>".format(self.name)


class Post(db.Model):
	""" Init the Model of `Post` """

	# SET the table name for Post `posts` 
	__tablename__ = 'posts'

	#SET the ForeignKey `user_id`
	user_id = db.Column(db.String(45), db.ForeignKey('users.id'))
	
	id = db.Column(db.String(45), primary_key=True)
	title = db.Column(db.String(255))
	text = db.Column(db.Text())
	publish_date = db.Column(db.DateTime)

	# Establish contact with Comment's ForeignKey: `post_id`
	comments = db.relationship(
		'Comment',
		backref = 'posts',
		lazy = 'dynamic')
	
	# Many TO Many: posts <=> tags
	# How to use
	# 1 Post <=> Tag by `tags` of Post:ins1_post.tags = [ins2_tag]
	# 				 				 :ins2_post.tags = [ins1_tag, ins3_tag, ins2_tag]
	# 2 Tag <=> Post by `posts` of backref list:ins1_tag.posts.append(ins1_post)
	tags = db.relationship(
		'Tag',
		secondary = posts_tags,
		backref = db.backref('posts', lazy = 'dynamic'))

	# INIT the Post's property of `id` `title`
	def __init__(self, id, title):
		self.id = id
		self.title = title

	# RETURN `<Model Post {title}` when print the Post instance
	def __repr__(self):
		return "<Model Post `{}`>".format(self.title)


class Comment(db.Model):
	"""" Init the Model `Comment` """

	# SET the talbe name for Comment `comments`
	__tablename__ = 'comments'
	
	# SET the ForeignKey for `post_id`
	post_id = db.Column(db.String(45), db.ForeignKey('posts.id'))
	
	id = db.Column(db.String(45), primary_key=True)
	name = db.Column(db.String(255))
	text = db.Column(db.Text())
	date = db.Column(db.DateTime())

	# INIT the Comment's property of `id` `name`
	def __init__(self, id, name):
		self.id = id
		self.name = name

	# RETURN `<Model Comment {name}` when print the Comment instance
	def __repr__(self):
		return '<Model Comment `{}`>'.format(self.name)


class Tag(db.Model):
	""" Init the Model `Tag` """

	# SET the table name for Tag `Tag`
	__tablename__ = 'tags'
	
	id = db.Column(db.String(45), primary_key=True)
	name = db.Column(db.String(255))
	
	#INIT the Tag's property of `id` `name`
	def __init__(self, id, name):
		self.id = id
		self.name = name
	
	# RETURN `<Model Tag {name}` when print the Tag instance
	def __repr__(self):
		return "<Model Tag `{}`>".format(self.name)
